#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fcntl.h"
#include "kernel/fs.h"
#include "kernel/btree.h"

void
itoa(int num, char* str) {
    int i = 0;
    int isNegative = 0;

    // 处理负数
    if (num < 0) {
        isNegative = 1;
        num = -num;
    }

    // 处理0的特殊情况
    if (num == 0) {
        str[i++] = '0';
        str[i] = '\0';
        return;
    }

    // 计算数字的位数
    while (num != 0) {
        int rem = num % 10;
        str[i++] = rem + '0';  // 将数字转换为字符
        num = num / 10;
    }

    // 如果是负数，添加负号
    if (isNegative) {
        str[i++] = '-';
    }

    str[i] = '\0';  // 添加字符串结束符

    // 反转字符串
    int start = 0;
    int end = i - 1;
    while (start < end) {
        char temp = str[start];
        str[start] = str[end];
        str[end] = temp;
        start++;
        end--;
    }
}

// void
// printbtn(int fd, struct btreenode *btn){
//   printf("%d block btreenode start\n", btn->block);
//   for(int i = 0; i < btn->numkeys; i++){
//     printf("%s ", btn->keys[i].name);
//   }
//   printf("\n%d block btreenode over\n", btn->block);
//   for(int i = 0; i < btn->childnum; i++){
//     if(btn->children[i] == 0){
//       printf("btree readdir failed\n");
//       close(fd);
//       exit(1);
//     }
//     struct btreenode newbtn;
//     rbtn(fd, &newbtn, sizeof(struct btreenode), btn->children[i]);
//     printbtn(fd, &newbtn);
//   }
// }

void dirtest(){
  if(mkdir("dir0") < 0){
    printf("mkdir failed\n");
    exit(1);
  }

  if(chdir("dir0") < 0){
    printf("chdir dir0 failed\n");
    exit(1);
  }

  if(chdir("..") < 0){
    printf("chdir .. failed\n");
    exit(1);
  }
}

void dirfile(){
  int fd;
  fd = open("dirfile", O_CREATE);
  if(fd < 0){
    printf("create dirfile failed\n");
    exit(1);
  }
  close(fd);
  if(chdir("dirfile") == 0){
    printf("chdir dirfile succeeded!\n");
    exit(1);
  }
  fd = open("dirfile/xx", 0);
  if(fd >= 0){
    printf("create dirfile/xx succeeded!\n");
    exit(1);
  }
  fd = open("dirfile/xx", O_CREATE);
  if(fd >= 0){
    printf("create dirfile/xx succeeded!\n");
    exit(1);
  }
  if(mkdir("dirfile/xx") == 0){
    printf("mkdir dirfile/xx succeeded!\n");
    exit(1);
  }

  fd = open(".", O_RDWR);
  if(fd >= 0){
    printf("open . for writing succeeded!\n");
    exit(1);
  }
  fd = open(".", 0);
  if(write(fd, "x", 1) > 0){
    printf("write . succeeded!\n");
    exit(1);
  }
  close(fd);
}

int num = 150;
void readdir(){
  // 创建0-149目录
  for(int i = 0; i < num; i++){
    char dirname[DIRSIZ]; // 确保这个数组足够大以存放字符串
    itoa(i, dirname); // 将整数i格式化为字符串"dirX"
    if(mkdir(dirname) < 0){
      printf("mkdir failed\n");
      exit(1);
    }
  }

  // 读出所有目录
  char buf[512], *p;
  char *path = ".";
  struct btreenode btn;
  int fd;

  if((fd = open(path, 0)) < 0){
    printf("open . for writing failed!\n");
    exit(1);
  }

  if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
    printf("path too long\n");
    close(fd);
    exit(1);
  }

  strcpy(buf, path);
  p = buf+strlen(buf);
  *p++ = '/';

  // 借助队列使用层序遍历
  struct SqQueue myQueue;
  uint e;
  Create_SqQueue(&myQueue);
  if(read(fd, &btn, sizeof(struct btreenode)) == sizeof(struct btreenode)){
    if(btn.block == 0){
      printf("btree readdir failed\n");
      close(fd);
      exit(1);
    }
    // printbtn(fd, &btn);
    printf("%d block btreenode start\n", btn.block);
    for(int i = 0; i < btn.numkeys; i++){
        printf("%s ", btn.keys[i].name);
    }
    printf("\n%d block btreenode over\n", btn.block);
    for(int i = 0; i < btn.childnum; i++){
      Enter_SqQueue(&myQueue, btn.children[i]);
    }
    // 队列不为空
    while(!IsEmpty(&myQueue)){
      // 读出队首的块号对应的btreenode结点
      rbtn(fd, &btn, sizeof(struct btreenode), Get_front(&myQueue));
      Depart_SqQueue(&myQueue, &e);
      // 输出btreenode结点
      printf("%d block btreenode start\n", btn.block);
      for(int i = 0; i < btn.numkeys; i++){
        printf("%s ", btn.keys[i].name);
      }
      printf("\n%d block btreenode over\n", btn.block);
      // 将btreenode结点的孩子结点加入队列
      for(int i = 0; i < btn.childnum; i++){
        Enter_SqQueue(&myQueue, btn.children[i]);
      }
    }
  }
  close(fd);
}
void finddir(){
  char dirname[DIRSIZ]; // 确保这个数组足够大以存放字符串
  printf("start time %d \n",uptime());
  for(int i = 0; i < num; i++){
    itoa(i, dirname); // 将整数i格式化为字符串"dirX"
    if(mkdir(dirname) < 0){
      printf("%d ",i);
    }
  }
  printf("\nend time %d \n",uptime());
}

int
main()
{
  printf("test btree dirtest: "); 
  dirtest();
  printf("ok\n"); 
  printf("test btree dirfile: "); 
  dirfile();
  printf("ok\n"); 
  printf("test btree readdir: \n"); 
  readdir();
  printf("ok\n"); 
  printf("test btree finddir: \n"); 
  finddir();
  printf("ok\n");
  exit(0);
}
